package u1;

import static java.lang.System.*;
import static java.lang.Math.*;
import static u1.Util.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;
import java.util.List;
import java.util.Map;

/**
 * Look up titles of some pages in each link histogram bucket. This is mainly
 * for testing. First argument is the titles list (see Titles.java); second
 * argument is the histogram (see LinkHistogram.java); third argument is the
 * maximum number of pages to recover from each bucket; fourth argument is a
 * filter list (optional) - only examples in this filter list will be included
 * in the output. Takes the adjacency list (see ForwardLinks.java or
 * BackwardLinks.java) on standard in and prints the results on standard out.
 */
public class LinkHistogramExamples {
  public static void main(String[] argv) throws IOException {
    if (argv.length < 3 || argv.length > 4) {
      err.println("See comments for usage.");
      exit(-1);
    }
    String titlesFile = argv[0];
    String histogramFile = argv[1];
    final Integer pagesPerBucket = Integer.decode(argv[2]);
    String filterFile = argv[3];

    /*
     * Read titles for lookups.
     */
    trace("Reading titles from %s...", titlesFile);
    BufferedReader titlesReader = new BufferedReader(new InputStreamReader(
        new FileInputStream(new File(titlesFile)), "UTF-8"));
    final List<String> titles = new ArrayList<String>(PAGES_MAX);
    readLines(titles, titlesReader);
    titlesReader.close();
    trace("Read %d titles.", titles.size());

    /*
     * Read histogram buckets. We only really need the buckets; use the counts
     * to keep track of how many pages we've found so far.
     */
    trace("Reading histogram from %s...", histogramFile);
    BufferedReader histReader = new BufferedReader(new InputStreamReader(
        new FileInputStream(new File(histogramFile)), "UTF-8"));
    final Map<Integer, Integer> hist = new HashMap<Integer, Integer>();
    readIntIntMap(hist, histReader);
    trace("Read %d buckets.", hist.size());
    histReader.close();

    // Don't return more than the configured number of examples per bucket.
    for (Map.Entry<Integer, Integer> e : hist.entrySet()) {
      e.setValue(min(e.getValue(), pagesPerBucket));
    }
    
    /*
     * Read filter, if any.
     */
    final Set<Integer> filter = new HashSet<Integer>();
    if (filterFile == null) {
      trace("Not using filter.");
    } else {
      List<Integer> filterList = new ArrayList<Integer>();
      readIntegers(filterList, new FileInputStream(new File(filterFile)));
      filter.addAll(filterList);
      trace("Read %d distinct pages from filter file.", filter.size());
    }

    /*
     * Read input adjacency list.
     */
    final Map<Integer, List<String>> examples = new TreeMap<Integer, List<String>>();
    trace("Reading adjacency list from stdin.");
    AdjReader adjReader = new AdjReader() {
      @Override
      public void readLinks(Integer source, Collection<Integer> targets) {
        if (!filter.isEmpty() && !filter.contains(source))
          return;
        Integer bucket = targets.size();
        Integer examplesLeft = hist.get(bucket);
        if (examplesLeft != null && examplesLeft > 0) {
          List<String> exampleList = examples.get(bucket);
          if (exampleList == null) {
            exampleList = new ArrayList<String>(pagesPerBucket);
            examples.put(bucket, exampleList);
          }
          exampleList.add(titles.get(source));
          hist.put(bucket, examplesLeft - 1);
        }
      }
    };
    adjReader.read(in);
    trace("Read %d pages (%d links) from adjacency list.", adjReader
        .getPageIndex(), adjReader.getLinkCount());

    /*
     * Output.
     */
    for (Map.Entry<Integer, List<String>> e : examples.entrySet()) {
      out.println("*** " + e.getKey() + " ***");
      for (String s : e.getValue()) {
        out.println(s);
      }
      out.println();
    }
  }
}
/*
* Copyright (c) 2009 John Lees-Miller
* 
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
* 
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

